package com.lhkj.ct.meta.modules.gauge.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.lhkj.ct.base.enums.DeleteStatus;
import com.lhkj.ct.base.mybatis.extension.service.impl.BatchHandleServiceImpl;
import com.lhkj.ct.base.utils.Validate;
import com.lhkj.ct.meta.modules.gauge.common.enums.ConfigProcess;
import com.lhkj.ct.meta.modules.gauge.mapper.ScaleMapper;
import com.lhkj.ct.meta.modules.gauge.mapper.ScaleDimensionMapper;
import com.lhkj.ct.meta.modules.gauge.model.entity.*;
import com.lhkj.ct.meta.modules.gauge.model.vo.ScaleDimensionVo;
import com.lhkj.ct.meta.modules.gauge.service.DimQuestionService;
import com.lhkj.ct.meta.modules.gauge.service.DimensionService;
import com.lhkj.ct.meta.modules.gauge.service.ScaleDimNormService;
import com.lhkj.ct.meta.modules.gauge.service.ScaleWarnSettingService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 量表维度 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2023-10-16
 */
@Service
public class DimensionServiceImpl extends BatchHandleServiceImpl<ScaleDimensionMapper, TblScaleDimension> implements DimensionService {

    @Resource
    private DimQuestionService dimQuestionService;

    @Resource
    private ScaleDimNormService dimNormService;

    @Resource
    private ScaleWarnSettingService warnSettingService;

    @Resource
    private ScaleMapper scaleMapper;

    @Override
    public List<ScaleDimensionVo> selectAllByScale(String scaleId) {
        return getBaseMapper().selectListByScale(scaleId);
    }

    @Override
    public TblScaleDimension getForm(String dimId) {
        return getBaseMapper().getForm(dimId);
    }

    @Override
    public boolean checkNameUnique(TblScaleDimension dimension) {
        LambdaQueryWrapper<TblScaleDimension> wrapper = new LambdaQueryWrapper<TblScaleDimension>()
                .select(TblScaleDimension::getId)
                .eq(TblScaleDimension::getDimName, dimension.getDimName())
                .eq(TblScaleDimension::getScaleId, dimension.getScaleId())
                .ne(StringUtils.isNotBlank(dimension.getId()), TblScaleDimension::getId, dimension.getId())
                // 性别
                .eq(StringUtils.isNotBlank(dimension.getSuitSex()), TblScaleDimension::getSuitSex, dimension.getSuitSex())
                .and(StringUtils.isBlank(dimension.getSuitSex()), w -> w.isNull(TblScaleDimension::getSuitSex).or().eq(TblScaleDimension::getSuitSex, ""));
        // 年龄区间
        if (null != dimension.getMinAge() && null != dimension.getMaxAge()) {
            wrapper.and(
                    w -> w.between(TblScaleDimension::getMinAge, dimension.getMinAge(), dimension.getMaxAge())
                            .or()
                            .between(TblScaleDimension::getMaxAge, dimension.getMinAge(), dimension.getMaxAge())
            );
        }
        return getBaseMapper().selectCount(wrapper) == 0;
    }

    @Override
    public boolean save(TblScaleDimension dimension) {
        TblScale scale = scaleMapper.selectById(dimension.getScaleId());
        Validate.isFalse(null == scale || DeleteStatus.DELETED.equals(scale.getDelFlag()), "量表不存在或已删除！");
        Validate.isFalse(ConfigProcess.BASIC.equals(scale.getProgress()), "请先配置题目！");
        // 更新配置进度
        if (ConfigProcess.QUESTION.equals(scale.getProgress())) {
            scaleMapper.update(null, new LambdaUpdateWrapper<TblScale>().set(TblScale::getProgress, ConfigProcess.DIMENSION).eq(TblScale::getId, scale.getId()));
        }
        boolean res = SqlHelper.retBool(getBaseMapper().insert(dimension));
        String dimId = dimension.getId();
        List<TblScaleDimQuestion> dimQuestions = dimension.getRelations()
                .stream()
                .peek(p -> p.setDimId(dimId))
                .collect(Collectors.toList());
        List<TblScaleDimNorm> norms = dimension.getNorms()
                .stream()
                .peek(p -> p.setDimId(dimId))
                .collect(Collectors.toList());
        List<TblScaleWarnSetting> warnSettings = dimension.getWarnSettings()
                .stream()
                .peek(p -> p.setDimId(dimId))
                .collect(Collectors.toList());
        dimQuestionService.saveBatch(dimQuestions);
        dimNormService.saveBatch(norms);
        warnSettingService.saveBatch(warnSettings);
        return res;
    }

    @Override
    public boolean update(TblScaleDimension dimension) {
        String dimId = dimension.getId();
        TblScaleDimension target = getForm(dimId);
        Validate.isFalse(null == target, "维度不存在！");
        dimension.setScaleId(target.getScaleId());
        getBaseMapper().updateById(dimension);
        // 处理题目关联
        handleRelationQuestion(dimension.getRelations().stream().peek(p -> p.setDimId(dimId)).collect(Collectors.toList()),
                target.getRelations());
        // 处理常模解释
        handleNorms(dimension.getNorms().stream().peek(p -> p.setDimId(dimId)).collect(Collectors.toList()),
                target.getNorms());
        // 处理预警设置
        handleWarnSetting(dimension.getWarnSettings().stream().peek(p -> p.setDimId(dimId)).collect(Collectors.toList()),
                target.getWarnSettings());
        return true;
    }

    @Override
    public int removeById(Serializable id) {
        TblScaleDimension dimension = getBaseMapper().selectById(id);
        if (null == dimension) {
            return 0;
        }
        Long count = getBaseMapper().selectCount(
                new LambdaQueryWrapper<TblScaleDimension>()
                        .select(TblScaleDimension::getId)
                        .eq(TblScaleDimension::getScaleId, dimension.getScaleId())
        );
        Validate.isFalse(count <= 1, "请至少设置一个维度！");
        List<TblScaleDimension> dimensions = getBaseMapper().selectList(new LambdaQueryWrapper<TblScaleDimension>()
                .select(TblScaleDimension::getDimName)
                .eq(TblScaleDimension::getScaleId, dimension.getScaleId())
                .isNotNull(TblScaleDimension::getFormula)
                .like(TblScaleDimension::getFormula, String.format("{{%s}}", dimension.getDimName()))
                .ne(TblScaleDimension::getId, id)
        );
        Validate.isTrue(dimensions.isEmpty(), "维度[%s]在%s公式中被使用，请先处理公式后进行删除", dimension.getDimName(), dimensions.stream().map(TblScaleDimension::getDimName).collect(Collectors.toSet()));
        return getBaseMapper().deleteById(id);
    }


    /**
     * 维度题目
     *
     * @param source 新的设置
     * @param target 旧的设置
     */
    private void handleRelationQuestion(List<TblScaleDimQuestion> source, List<TblScaleDimQuestion> target) {
        if (CollectionUtils.isEqualCollection(source, target)) {
            return;
        }
        // 收集旧的题目id，用来判断是否有删除的题目
        List<String> oldRelationIds = target.stream().map(TblScaleDimQuestion::getId).collect(Collectors.toList());
        // 按照题目id进行合并
        Map<String, TblScaleDimQuestion> questionMap = target.stream()
                .collect(Collectors.toMap
                        (TblScaleDimQuestion::getId, each -> each, (value1, value2) -> value1));
        // 收集新增的题目
        List<TblScaleDimQuestion> relations = new ArrayList<>();
        // 收集有变化的
        List<TblScaleDimQuestion> variable = new ArrayList<>();
        // 处理排序
        for (TblScaleDimQuestion relation : source) {
            // 新增
            if (StringUtils.isBlank(relation.getId())) {
                relations.add(relation);
                continue;
            }
            oldRelationIds.remove(relation.getQutId());
            // 无变化
            if (target.remove(relation)) {
                continue;
            }
            // 修改
            if (questionMap.containsKey(relation.getId())) {
                variable.add(relation);
            }
        }
        // 批量新增题目
        dimQuestionService.saveBatch(relations);
        dimQuestionService.updateBatchById(variable);
        if (CollectionUtil.isNotEmpty(oldRelationIds)) {
            dimQuestionService.removeByIds(oldRelationIds);
        }

    }

    /**
     * 常模解释
     *
     * @param source 新的设置
     * @param target 旧的设置
     */
    private void handleNorms(List<TblScaleDimNorm> source, List<TblScaleDimNorm> target) {
        if (CollectionUtils.isEqualCollection(source, target)) {
            return;
        }
        // 收集旧的题目id，用来判断是否有删除的题目
        List<String> oldRelationIds = target.stream().map(TblScaleDimNorm::getNormId).collect(Collectors.toList());
        // 按照题目id进行合并
        Map<String, TblScaleDimNorm> questionMap = target.stream()
                .collect(Collectors.toMap
                        (TblScaleDimNorm::getNormId, each -> each, (value1, value2) -> value1));
        // 收集新增的题目
        List<TblScaleDimNorm> relations = new ArrayList<>();
        // 收集有变化的
        List<TblScaleDimNorm> variable = new ArrayList<>();
        // 处理排序
        for (TblScaleDimNorm relation : source) {
            // 新增
            if (StringUtils.isBlank(relation.getNormId())) {
                relations.add(relation);
                continue;
            }
            oldRelationIds.remove(relation.getNormId());
            // 无变化
            if (target.remove(relation)) {
                continue;
            }
            // 修改
            if (questionMap.containsKey(relation.getNormId())) {
                variable.add(relation);
            }
        }
        // 批量新增题目
        dimNormService.saveBatch(relations);
        dimNormService.updateBatchById(variable);
        if (CollectionUtil.isNotEmpty(oldRelationIds)) {
            dimNormService.removeByIds(oldRelationIds);
        }

    }

    /**
     * 预警设置
     *
     * @param source 新的设置
     * @param target 旧的设置
     */
    private void handleWarnSetting(List<TblScaleWarnSetting> source, List<TblScaleWarnSetting> target) {
        if (CollectionUtils.isEqualCollection(source, target)) {
            return;
        }
        // 收集旧的预警id，用来判断是否有删除的预警设置
        List<String> oldRelationIds = target.stream().map(TblScaleWarnSetting::getId).collect(Collectors.toList());
        // 按照预警id进行合并
        Map<String, TblScaleWarnSetting> questionMap = target.stream()
                .collect(Collectors.toMap
                        (TblScaleWarnSetting::getId, each -> each, (value1, value2) -> value1));
        // 收集新增的
        List<TblScaleWarnSetting> relations = new ArrayList<>();
        // 收集有变化的
        List<TblScaleWarnSetting> variable = new ArrayList<>();
        // 处理排序
        for (TblScaleWarnSetting setting : source) {
            // 新增
            if (StringUtils.isBlank(setting.getId())) {
                relations.add(setting);
                continue;
            }
            oldRelationIds.remove(setting.getId());
            // 无变化
            if (target.remove(setting)) {
                continue;
            }
            // 修改
            if (questionMap.containsKey(setting.getId())) {
                variable.add(setting);
            }
        }
        // 批量新增
        warnSettingService.saveBatch(relations);
        // 批量修改
        warnSettingService.updateBatchById(variable);
        if (CollectionUtil.isNotEmpty(oldRelationIds)) {
            warnSettingService.removeByIds(oldRelationIds);
        }

    }
}
